home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cfengine-1.5.3 / src / cfd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-25  |  50.0 KB  |  2,178 lines

  1. /* 
  2.  
  3.         Copyright (C) 1995,96,97,98
  4.         Free Software Foundation, Inc.
  5.  
  6.    This file is part of GNU cfengine - written and maintained 
  7.    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
  8.    Dept. of Theoretical physics, University of Oslo
  9.  
  10.    This program is free software; you can redistribute it and/or modify it
  11.    under the terms of the GNU General Public License as published by the
  12.    Free Software Foundation; either version 2, or (at your option) any
  13.    later version.
  14.  
  15.    This program is distributed in the hope that it will be useful,
  16.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.    GNU General Public License for more details.
  19.  
  20.   You should have received a copy of the GNU General Public License
  21.   along with this program; if not, write to the Free Software
  22.   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
  23.  
  24. */
  25.  
  26. /*******************************************************************/
  27. /*                                                                 */
  28. /*  Cfengine : remote server daemon example                        */
  29. /*                                                                 */
  30. /*******************************************************************/
  31.  
  32. #define INET 1
  33.  
  34.  
  35. #include "cf.defs.h"
  36. #include "cf.extern.h"
  37. #include "../pub/getopt.h"
  38. #include "cfd.h"
  39.  
  40. #ifdef HAVE_TCPD_H
  41. # include <tcpd.h>
  42. #endif
  43.  
  44. #ifdef HAVE_PTHREAD_H
  45. # include <pthread.h>
  46. #endif
  47.  
  48. #ifdef HAVE_SCHED_H
  49. # include <sched.h>
  50. #endif
  51.  
  52. #ifdef HAVE_PTHREAD_H
  53. pthread_attr_t PTHREADDEFAULTS;
  54. pthread_mutex_t MUTEX_COUNT = PTHREAD_MUTEX_INITIALIZER;
  55. pthread_mutex_t MUTEX_HOSTNAME = PTHREAD_MUTEX_INITIALIZER;
  56. #endif
  57.  
  58. /*******************************************************************/
  59. /* Level 0 : Main                                                  */
  60. /*******************************************************************/
  61.  
  62. main (argc,argv)
  63.  
  64. int argc;
  65. char **argv;
  66.  
  67. {
  68. CheckOptsAndInit(argc,argv);
  69. GetNameInfo();
  70. ParseInputFiles();
  71.  
  72. if (PARSEONLY)
  73.    {
  74.    exit(0);
  75.    }
  76.  
  77. CheckVariables();
  78. SummarizeParsing();
  79. StartServer(argc,argv);
  80.  
  81. /* Never exit here */
  82. }
  83.  
  84. /********************************************************************/
  85. /* Level 1                                                          */
  86. /********************************************************************/
  87.  
  88. CheckOptsAndInit(argc,argv)
  89.  
  90. int argc;
  91. char **argv;
  92.  
  93. { extern char *optarg;
  94.  int optindex = 0;
  95.   int c, i;
  96.  
  97. umask(0);
  98. openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_DAEMON);
  99. strcpy(VINPUTFILE,CFD_INPUT);
  100. OUTPUT[0] = '\0';
  101. VFQNAME[0] = '\0';
  102.  
  103. ISCFENGINE = false;   /* Switch for the parser */
  104. PARSEONLY  = false;
  105.  
  106. InitHashTable();
  107.  
  108. AddClassToHeap("any");      /* This is a reserved word / wildcard */
  109.  
  110. while ((c=getopt_long(argc,argv,"d:f:vmhpFV",CFDOPTIONS,&optindex)) != EOF)
  111.   {
  112.   switch ((char) c)
  113.       {
  114.       case 'f': strncpy(VINPUTFILE,optarg,bufsize-1);
  115.                 break;
  116.  
  117.       case 'd': 
  118.  
  119.                 switch (*optarg)
  120.                    {
  121.                    case '1': D1 = true;
  122.                              break;
  123.                    case '2': D2 = true;
  124.                              break;
  125.                    default:  DEBUG = true;
  126.                              break;
  127.                    }
  128.         
  129.         NO_FORK = true;
  130.         printf("cfd: Debug mode: running in foreground\n");
  131.                 break;
  132.  
  133.       case 'v': VERBOSE = true;
  134.             break;
  135.  
  136.       case 'V': printf("GNU %s daemon\n%s\n",CFVERSION,COPYRIGHT);
  137.             printf("This program is covered by the GNU Public License and may be\n");
  138.         printf("copied free of charge. No warrenty is implied.\n\n");
  139.                 exit(0);
  140.             break;
  141.  
  142.       case 'p': PARSEONLY = true;
  143.             break;
  144.  
  145.       case 'F': NO_FORK = true;
  146.             break;
  147.  
  148.       case 'm': /* No longer needed */
  149.             break;
  150.  
  151.       default:  Syntax();
  152.                 exit(1);
  153.  
  154.       }
  155.    }
  156.  
  157.  
  158. LOGGING = true;                    /* Do output to syslog */
  159.  
  160. sprintf(VPREFIX,"cfd:%s:",VUQNAME); 
  161. sprintf(VBUFF,"%s/test",LOCKFILEDIR);
  162. MakeDirectoriesFor(VBUFF);
  163. strncpy(VLOCKDIR,LOCKFILEDIR,bufsize-1);
  164.  
  165. sprintf(VBUFF,"%s/test",LOGFILEDIR);
  166.  
  167. MakeDirectoriesFor(VBUFF);
  168. strncpy(VLOGDIR,LOGFILEDIR,bufsize-1);
  169.  
  170. strcpy(VDOMAIN,"undefined.domain");
  171.  
  172. strncpy(VCANONICALFILE,CanonifyName(VINPUTFILE),bufsize-1);
  173. }
  174.  
  175. /*******************************************************************/
  176.  
  177. CheckVariables()
  178.  
  179. { struct stat statbuf;
  180.   int i, value = -1;
  181.  
  182. #ifdef HAVE_LIBPTHREAD
  183.  CfLog(cfinform,"Multithreaded version","");
  184. #else
  185.  CfLog(cfinform,"Single threaded version","");
  186. #endif
  187.  
  188. strncpy(VFQNAME,VSYSNAME.nodename,bufsize-1);
  189. LoadSecretKeys();
  190.  
  191. if ((CFDSTARTTIME = time((time_t *)NULL)) == -1)
  192.    {
  193.    printf("Couldn't read system clock\n");
  194.    }
  195.  
  196. if (GetMacroValue("CheckIdent") && (strcmp(GetMacroValue("CheckIdent"),"on") == 0))
  197.    {
  198.    CHECK_RFC931 = true;
  199.    }
  200.  
  201. if (GetMacroValue("DenyBadClocks") && (strcmp(GetMacroValue("DenyBadClocks"),"off") == 0))
  202.    {
  203.    DENYBADCLOCKS = false;
  204.    }
  205.  
  206.  
  207. bzero(CHECKSUMDB,bufsize);
  208.  
  209. if (GetMacroValue("ChecksumDatabase"))
  210.    {
  211.    ExpandVarstring("$(ChecksumDatabase)",CHECKSUMDB,NULL);
  212.  
  213.    if (*CHECKSUMDB != '/')
  214.       {
  215.       FatalError("$(ChecksumDatabase) does not expand to an absolute filename\n");
  216.       }
  217.    }
  218.  
  219.  
  220.  
  221. if (GetMacroValue("IfElapsed"))
  222.    {
  223.    ExpandVarstring("$(IfElapsed)",VBUFF,NULL);
  224.    sscanf(VBUFF,"%d",&value);
  225.  
  226.    if (value < 0)
  227.       {
  228.       printf("cfd: silly IfElapsed value in control\n");
  229.       exit(1);
  230.       }
  231.    else
  232.       {
  233.       VIFELAPSED = value;
  234.       Verbose("cfd: IfElapsed time: %d minutes\n",VIFELAPSED);
  235.       }
  236.    }
  237.   
  238. bzero(VBUFF,bufsize);
  239.  
  240. if (GetMacroValue("cfrunCommand"))
  241.    {
  242.    ExpandVarstring("$(cfrunCommand)",VBUFF,NULL);
  243.  
  244.    if (*VBUFF != '/')
  245.       {
  246.       FatalError("$(cfrunCommand) does not expand to an absolute filename\n");
  247.       }
  248.  
  249.    sscanf(VBUFF,"%4095s",CFRUNCOMMAND);
  250.    Debug("cfrunCommand is %s\n",CFRUNCOMMAND);
  251.  
  252.    if (stat(CFRUNCOMMAND,&statbuf) == -1)
  253.       {
  254.       FatalError("$(cfrunCommand) points to a non-existent file\n");
  255.       }
  256.    }
  257.  
  258. if (GetMacroValue("MaxConnections"))
  259.    {
  260.    bzero(VBUFF,bufsize);
  261.    ExpandVarstring("$(MaxConnections)",VBUFF,NULL);
  262.    Debug("$(MaxConnections) Expanded to %s\n",VBUFF);
  263.  
  264.    CFD_MAXPROCESSES = atoi(VBUFF);
  265.  
  266.    if ((CFD_MAXPROCESSES < 1) || (CFD_MAXPROCESSES > 100))
  267.       {
  268.       FatalError("cfd: MaxConnections with silly value");
  269.       }
  270.     }
  271. else
  272.    {
  273.    CFD_MAXPROCESSES = 10;
  274.    }
  275.  
  276. if (GetMacroValue("AutoExecInterval"))
  277.    {
  278.    bzero(VBUFF,bufsize);
  279.    ExpandVarstring("$(AutoExecInterval)",VBUFF,NULL);
  280.    Debug("$(AutoExecInterval) Expanded to %s\n",VBUFF);
  281.  
  282.    CFD_INTERVAL = 60 * atoi(VBUFF);
  283.  
  284.    if ((CFD_INTERVAL < 0) || (CFD_INTERVAL > 60*24*7))
  285.       {
  286.       FatalError("cfd: AutoExecInterval with silly value in minutes (>0 and less than 1 week)");
  287.       }
  288.    }
  289. else
  290.    {
  291.    CFD_INTERVAL = 0;
  292.    }
  293.  
  294. Debug("MaxConnections = %d\n",CFD_MAXPROCESSES);
  295. Debug("AutoExecInterval = %d\n",CFD_INTERVAL);
  296.  
  297. CHECKSUMUPDATES = true;
  298.  
  299. if (GetMacroValue("ChecksumUpdates") && (strcmp(GetMacroValue("ChecksumUpdates"),"off") == 0))
  300.   {
  301.   CHECKSUMUPDATES = false;
  302.   } 
  303.  
  304. i = 0;
  305.  
  306. if (strstr(VSYSNAME.nodename,ToLowerStr(VDOMAIN)))
  307.    {
  308.    strncpy(VFQNAME,VSYSNAME.nodename,bufsize-1);
  309.    
  310.    while(VSYSNAME.nodename[i++] != '.')
  311.       {
  312.       }
  313.    
  314.    strncpy(VUQNAME,VSYSNAME.nodename,i-1);
  315.    }
  316. else
  317.    {
  318.    sprintf(VFQNAME,"%s.%s",VSYSNAME.nodename,ToLowerStr(VDOMAIN));
  319.    strncpy(VUQNAME,VSYSNAME.nodename,bufsize-1);
  320.    }
  321. }
  322.  
  323. /*******************************************************************/
  324.  
  325. SummarizeParsing()
  326.  
  327. { struct Auth *ptr;
  328.   struct Item *ip,*ipr;
  329.   
  330. if (DEBUG || D2 || D3)
  331.    {
  332.    printf("ACCESS GRANTED ----------------------:\n\n");
  333.  
  334.    for (ptr = VADMIT; ptr != NULL; ptr=ptr->next)
  335.       {
  336.       printf("Path: %s (secure=%d)\n",ptr->path,ptr->secure);
  337.  
  338.       for (ip = ptr->accesslist; ip != NULL; ip=ip->next)
  339.      {
  340.      printf("   Admit: %s root=",ip->name);
  341.      for (ipr = ptr->maproot; ipr !=NULL; ipr=ipr->next)
  342.         {
  343.         printf("%s,",ipr->name);
  344.         }
  345.      printf("\n");
  346.      }
  347.       }
  348.  
  349.    printf("ACCESS DENIAL ------------------------ :\n\n");
  350.  
  351.    for (ptr = VDENY; ptr != NULL; ptr=ptr->next)
  352.       {
  353.       printf("Path: %s\n",ptr->path);
  354.  
  355.       for (ip = ptr->accesslist; ip != NULL; ip=ip->next)
  356.      {
  357.      printf("   Deny: %s\n",ip->name);
  358.      }      
  359.       }
  360.    
  361.    printf("Hosts denied access to :\n\n");
  362.    }
  363.  
  364.  
  365. if (ERRORCOUNT > 0)
  366.    {
  367.    FatalError("Execution terminated after parsing due to errors in program");
  368.    }
  369. }
  370.  
  371. /*******************************************************************/
  372.  
  373. StartServer(argc,argv)
  374.  
  375. int argc;
  376. char **argv;
  377.  
  378. { struct sockaddr_in cin, sin; 
  379.   char recvbuffer[bufsize], sendbuffer[bufsize];
  380.   struct servent *server;
  381.   int sd, sd_reply, addrlen = sizeof(cin),ageing;
  382.   struct cfd_connection *conn;
  383.   int portnumber, yes=1, shmid;
  384.   struct linger cflinger;
  385.   void ExitCleanly(), AutoExec();
  386.  
  387. /* Initialize cflinger */
  388.  
  389. cflinger.l_onoff = 1;
  390. cflinger.l_linger = 60;
  391.   
  392. if ((!NO_FORK) && (fork() != 0))
  393.    {
  394.    sprintf(OUTPUT,"cfd: starting %.24s\n",ctime(&CFDSTARTTIME));
  395.    CfLog(cfinform,OUTPUT,"");
  396.    exit(0);
  397.    }
  398.  
  399. if (!NO_FORK)
  400.   {
  401. #ifdef HAVE_SETSID
  402.   setsid();
  403. #endif 
  404.   fclose (stdin);
  405.   fclose (stdout);
  406.   fclose (stderr);
  407.   closelog();
  408.   }
  409.  
  410. signal(SIGINT,ExitCleanly);
  411. signal(SIGTERM,ExitCleanly);
  412. signal(SIGHUP,SIG_IGN);
  413. signal(SIGPIPE,SIG_IGN);
  414. signal(SIGALRM,(void *)AutoExec);
  415.  
  416. sprintf(OUTPUT,"Setting alarm to %d seconds\n",CFD_INTERVAL); 
  417. CfLog(cfinform,OUTPUT,""); 
  418. alarm(CFD_INTERVAL);
  419.  
  420. if ((server = getservbyname(CFENGINE_SERVICE,"tcp")) == NULL)
  421.    {
  422.    CfLog(cferror,"Couldn't get cfengine service","getservbyname");
  423.    exit (1);
  424.    }
  425.  
  426. bzero(&cin,sizeof(cin));
  427.  
  428. sin.sin_port = (unsigned short)(server->s_port); /*  Service returns network byte order */
  429. sin.sin_addr.s_addr = INADDR_ANY;
  430. sin.sin_family = AF_INET; 
  431.  
  432. if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
  433.    {
  434.    CfLog(cferror,"Couldn't open socket","socket");
  435.    exit (1);
  436.    }
  437.  
  438. if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof (int)) == -1)
  439.    {
  440.    CfLog(cferror,"Couldn't set socket options","sockopt");
  441.    exit (1);
  442.    }
  443.  
  444.  if (setsockopt (sd, SOL_SOCKET, SO_LINGER, (char *) &cflinger, sizeof (struct linger)) == -1)
  445.    {
  446.    CfLog(cferror,"Couldn't set socket options","sockopt");
  447.    exit (1);
  448.    }
  449.  
  450. if (bind(sd,(struct sockaddr *)&sin,sizeof(sin)) == -1)  /* Must have this on server */
  451.    {
  452.    CfLog(cferror,"Couldn't bind to socket","bind");
  453.    exit(1);
  454.    }
  455.  
  456. if (listen(sd,queuesize) == -1)
  457.    {
  458.    CfLog(cferror,"listen failed","listen");
  459.    exit(1);
  460.    }
  461.  
  462. Verbose("Listening for connections on port %d..\n",ntohs(server->s_port));
  463.  
  464. ageing = 0;
  465.  
  466. while (true)
  467.    {
  468.    if ((sd_reply = accept(sd, (struct sockaddr *)&cin, &addrlen)) == -1)
  469.       {
  470.       continue;
  471.       }
  472.    else
  473.       {
  474.       if (ageing++ > CFD_MAXPROCESSES*4) /* Insurance against stale db */
  475.      {                               /* estimate number of clients */
  476.      unlink(CHECKSUMDB);             /* arbitrary policy ..        */
  477.      ageing = 0;
  478.      }
  479.       SpawnConnection(sd_reply);
  480.       CheckFileChanges(argc,argv,sd);
  481.       }
  482.    }
  483. }
  484.  
  485. /*********************************************************************/
  486. /* Level 2                                                           */
  487. /*********************************************************************/
  488.  
  489. Syntax()
  490.  
  491. { int i;
  492.  
  493. printf("GNU cfengine daemon: server module\n%s\n%s\n",CFVERSION,COPYRIGHT);
  494. printf("\n");
  495. printf("Options:\n\n");
  496.  
  497. for (i=0; CFDOPTIONS[i].name != NULL; i++)
  498.    {
  499.    printf("--%-20s    (-%c)\n",CFDOPTIONS[i].name,(char)CFDOPTIONS[i].val);
  500.    }
  501.  
  502. printf("\nBug reports to bug-cfengine@prep.ai.mit.edu (News: gnu.cfengine.bug)\n");
  503. printf("General help to help-cfengine@prep.ai.mit.edu (News: gnu.cfengine.help)\n");
  504. printf("Info & fixes at http://www.iu.hioslo.no/~mark/cfengine.html\n");
  505. }
  506.  
  507. /*********************************************************************/
  508.  
  509. SpawnConnection(sd_reply)
  510.  
  511. int sd_reply;
  512.  
  513. { struct cfd_connection *conn;
  514.   struct cfd_connection *NewConn();
  515.  
  516. #ifdef HAVE_PTHREAD_H
  517.  pthread_t tid;
  518.  size_t size = 0;
  519. #endif
  520.   void *HandleConnection();
  521.  
  522. Debug("New connection...\n");
  523. conn = NewConn(sd_reply);
  524.  
  525. #ifdef HAVE_LIBPTHREAD
  526.  
  527. Debug("Spawning new thread...\n");
  528.  
  529. pthread_attr_init(&PTHREADDEFAULTS);
  530. pthread_attr_setdetachstate(&PTHREADDEFAULTS,PTHREAD_CREATE_DETACHED);
  531.  
  532. #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
  533.  pthread_attr_setstacksize(&PTHREADDEFAULTS,(size_t)(sysconf(_SC_THREAD_STACK_MIN)+100*1024));
  534. #endif
  535.  
  536. if (pthread_create(&tid,&PTHREADDEFAULTS,HandleConnection,(void *)conn) != 0)
  537.    {
  538.    CfLog(cferror,"pthread_create failed","create");
  539.    HandleConnection(conn);
  540.    }
  541.  
  542. pthread_attr_destroy(&PTHREADDEFAULTS);
  543.  
  544. #else
  545.  
  546. /* Can't fork here without getting a zombie on some systems ? */
  547.  
  548. Debug("Single threaded...\n");
  549.  
  550. HandleConnection(conn);
  551.  
  552. #endif
  553. }
  554.  
  555. /**************************************************************/
  556.  
  557. CheckFileChanges(argc,argv,sd)
  558.  
  559. int argc;
  560. char **argv;
  561. int sd;
  562.  
  563. { struct stat newstat;
  564.   char filename[bufsize],line[bufsize], *sp;
  565.   char arg[maxshellargs][bufsize];
  566.   FILE *pp;
  567.   int i;
  568.   
  569. bzero(&newstat,sizeof(struct stat));
  570. bzero(filename,bufsize);
  571.  
  572. if ((sp=getenv(CFINPUTSVAR)) != NULL)
  573.    {
  574.    if (! IsAbsoluteFileName(VINPUTFILE))     /* Don't prepend to absolute names */
  575.       { 
  576.       strncpy(filename,sp,bufsize-1);
  577.       AddSlash(filename);
  578.       }
  579.    }
  580.  
  581. strcat(filename,VINPUTFILE);
  582.  
  583. if (stat(filename,&newstat) == -1)
  584.    {
  585.    sprintf(OUTPUT,"Input file %s missing!\n",filename);
  586.    CfLog(cferror,OUTPUT,filename);
  587.    return;
  588.    }
  589.  
  590. Debug("Checking file updates on %s (%x/%x)\n",filename, newstat.st_ctime, CFDSTARTTIME);
  591.  
  592. if (CFDSTARTTIME < newstat.st_ctime)
  593.    {
  594.    sprintf(OUTPUT,"Rereading config files %s..\n",filename);
  595.    CfLog(cfinform,OUTPUT,"");
  596.  
  597.    /* Free up memory */
  598.    
  599.    for (i = 0; i < hashtablesize; i++)
  600.       {
  601.       if (HASH[i] != NULL)
  602.      {
  603.      free(HASH[i]);
  604.      HASH[i] = NULL;
  605.      }
  606.       }
  607.  
  608.    DeleteItemList(VHEAP);
  609.    DeleteItemList(VNEGHEAP);
  610.    DeleteAuthList(VADMIT);
  611.    strcpy(VDOMAIN,"undefined.domain");
  612.    
  613.    VADMIT = VADMITTOP = NULL;
  614.    VHEAP = VNEGHEAP = NULL;
  615.  
  616.    AddClassToHeap("any");
  617.    GetNameInfo();
  618.    ParseInputFiles();
  619.    CheckVariables();
  620.    LoadSecretKeys();
  621.    alarm(CFD_INTERVAL);
  622.    }
  623. }
  624.  
  625. /*********************************************************************/
  626. /* Level 3                                                           */
  627. /*********************************************************************/
  628.  
  629. void *HandleConnection(conn)
  630.  
  631. struct cfd_connection *conn;
  632.  
  633. {
  634. #if defined HAVE_PTHREAD_H && defined HAVE_LIBPTHREAD
  635. #ifdef HAVE_PTHREAD_SIGMASK
  636.  sigset_t sigmask;
  637.  
  638. sigemptyset(&sigmask);
  639. pthread_sigmask(SIG_BLOCK,&sigmask,NULL); 
  640. #endif
  641.  
  642. if (pthread_mutex_lock(&MUTEX_COUNT) != 0)
  643.    {
  644.    CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");
  645.    DeleteConn(conn);
  646.    return NULL;
  647.    }
  648.  
  649. ACTIVE_THREADS++;
  650.  
  651. if (pthread_mutex_unlock(&MUTEX_COUNT) != 0)
  652.    {
  653.    CfLog(cferror,"pthread_mutex_unlock failed","unlock");
  654.    }  
  655.  
  656. if (ACTIVE_THREADS >= CFD_MAXPROCESSES)
  657.    {
  658.    CfLog(cfinform,"Too many threads","");
  659.    DeleteConn(conn);
  660.    return;
  661.    }
  662.  
  663. #endif
  664.  
  665. while (BusyWithConnection(conn))
  666.    {
  667.    }
  668.  
  669. DeleteConn(conn);
  670.  
  671. #ifdef HAVE_LIBPTHREAD
  672.  
  673.  Debug("Terminating thread...\n");
  674.  
  675. if (pthread_mutex_lock(&MUTEX_COUNT) != 0)
  676.    {
  677.    CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");
  678.    return;
  679.    }
  680.  
  681. ACTIVE_THREADS--;
  682.  
  683. if (pthread_mutex_unlock(&MUTEX_COUNT) != 0)
  684.    {
  685.    CfLog(cferror,"pthread_mutex_unlock failed","unlock");
  686.    }
  687.  
  688. #endif
  689.  
  690. }
  691.  
  692. /*********************************************************************/
  693.  
  694. BusyWithConnection(conn)
  695.  
  696. struct cfd_connection *conn;
  697.  
  698.   /* This is the protocol section. Here we must   */
  699.   /* check that the incoming data are sensible    */
  700.   /* and extract the information from the message */
  701.  
  702. { time_t tloc, trem = 0;
  703.   char recvbuffer[bufsize], sendbuffer[bufsize],check[bufsize];  
  704.   char filename[bufsize],buffer[bufsize],args[bufsize],out[bufsize];
  705.   long time_no_see = 0;
  706.   int len=0, drift;
  707.   struct cfd_get_arg get_args;
  708.  
  709. bzero(recvbuffer,bufsize);
  710. bzero(&get_args,sizeof(get_args));
  711.  
  712. if (RecvSocketStream(conn->sd_reply,recvbuffer,bufsize,NULL) == -1)
  713.    {
  714.    return false;
  715.    }
  716.  
  717. recvbuffer[bufsize-1] = '\0';
  718.  
  719. if (strlen(recvbuffer) == 0)
  720.    {
  721.    Debug("cfd: terminating NULL transmission!\n");
  722.    return false;
  723.    }
  724.   
  725. Debug("Received: [%s] on socket %d\n",recvbuffer,conn->sd_reply);
  726.  
  727. switch (GetCommand(recvbuffer))
  728.    {
  729.    case cfd_exec:    bzero(args,bufsize);
  730.                      sscanf(recvbuffer,"EXEC %[^\n]",args);
  731.  
  732.              if (! conn->id_verified)
  733.             {
  734.             RefuseAccess(conn,sendbuffer);
  735.             return false;
  736.             }
  737.  
  738.              if (!AccessControl(CFRUNCOMMAND,conn,false))
  739.             {
  740.             RefuseAccess(conn,sendbuffer);
  741.             return false;            
  742.             }
  743.  
  744.                   if (!MatchClasses(conn))
  745.             {
  746.             Terminate(conn->sd_reply);
  747.             return false;
  748.             }
  749.  
  750.              alarm(CFD_INTERVAL); /* reset alarm */
  751.  
  752.              DoExec(conn,sendbuffer,args);
  753.              Terminate(conn->sd_reply);
  754.              return false;
  755.  
  756.    case cfd_auth:    sprintf (sendbuffer,"BAD: Old protocol, you need to upgrade to 1.5.x\n");
  757.                      SendTransaction(conn,sendbuffer);
  758.                      return false;
  759.              
  760.    case cfd_cauth:   conn->id_verified = VerifyConnection(conn,(char *)(recvbuffer+strlen("CAUTH ")));
  761.                      if (! conn->id_verified)
  762.             {
  763.             RefuseAccess(conn,sendbuffer);
  764.             }
  765.                      return conn->id_verified; /* are we finished yet ? */
  766.  
  767.    case cfd_get:     bzero(filename,bufsize);
  768.                      sscanf(recvbuffer,"GET %d %[^\n]",&(get_args.buf_size),filename);
  769.  
  770.              if (get_args.buf_size < 0 || get_args.buf_size > bufsize)
  771.             {
  772.             RefuseAccess(conn,sendbuffer);
  773.             return false;
  774.             }
  775.  
  776.                   if (! conn->id_verified)
  777.             {
  778.             RefuseAccess(conn,sendbuffer);
  779.             return false;
  780.             }
  781.  
  782.              if (!AccessControl(filename,conn,false))
  783.             {
  784.             RefuseAccess(conn,sendbuffer);
  785.             return false;            
  786.             }
  787.  
  788.              bzero(sendbuffer,bufsize);
  789.              
  790.              get_args.connect = conn;
  791.              get_args.secure = false;
  792.              get_args.replybuff = sendbuffer;
  793.              get_args.replyfile = filename;
  794.              
  795.              CfGetFile(&get_args);
  796.              
  797.              return true;
  798.  
  799.    case cfd_sget:    bzero(buffer,bufsize);
  800.                      sscanf(recvbuffer,"SGET %d %d",&len,&(get_args.buf_size));
  801.                      bcopy(recvbuffer+31,out,bufsize-32);
  802.                      cfdecrypt(out,buffer,CFDES1,CFDES2,CFDES3,len);
  803.              
  804.              sscanf(buffer,"%3s %8s %[^\n]",check,get_args.key,filename);
  805.              Debug("Buffer was %s\n",buffer);
  806.  
  807.              if (strcmp(check,"GET") != 0)
  808.             {
  809.             RefuseAccess(conn,sendbuffer);
  810.             return false;
  811.             }
  812.  
  813.              if (get_args.buf_size < 0 || get_args.buf_size > 8192)
  814.             {
  815.             RefuseAccess(conn,sendbuffer);
  816.             return false;
  817.             }
  818.              
  819.              Debug("Confirm decryption, and thus validity of caller\n");
  820.              Debug("SGET %s with blocksize %d\n",filename,get_args.buf_size);
  821.  
  822.                   if (! conn->id_verified)
  823.             {
  824.             RefuseAccess(conn,sendbuffer);
  825.             return false;
  826.             }
  827.  
  828.              if (!AccessControl(filename,conn,true))
  829.             {
  830.             RefuseAccess(conn,sendbuffer);
  831.             return false;            
  832.             }
  833.  
  834.              bzero(sendbuffer,bufsize);
  835.              
  836.              get_args.connect = conn;
  837.              get_args.secure = true;
  838.              get_args.replybuff = sendbuffer;
  839.              get_args.replyfile = filename;
  840.              
  841.              CfGetFile(&get_args);
  842.              return true;
  843.              
  844.    case cfd_opendir: bzero(filename,bufsize);
  845.                      sscanf(recvbuffer,"OPENDIR %[^\n]",filename);
  846.              
  847.              if (! conn->id_verified)
  848.             {
  849.             RefuseAccess(conn,sendbuffer);
  850.             return false;
  851.             }
  852.  
  853.              if (!AccessControl(filename,conn,false))
  854.             {
  855.             RefuseAccess(conn,sendbuffer);
  856.             return false;            
  857.             }             
  858.  
  859.              CfOpenDirectory(conn,sendbuffer,filename);
  860.                      return true;
  861.  
  862.  
  863.    case cfd_ssynch:  bzero(buffer,bufsize);
  864.                      sscanf(recvbuffer,"SSYNCH %d",&len);
  865.                      bcopy(recvbuffer+23,out,bufsize-24);
  866.                      cfdecrypt(out,recvbuffer,CFDES1,CFDES2,CFDES3,len);
  867.              if (strncmp(recvbuffer,"SYNCH",5) !=0)
  868.             {
  869.             RefuseAccess(conn,sendbuffer);
  870.             return false;
  871.             }
  872.              /* roll through, no break */
  873.              
  874.    case cfd_synch:
  875.              if (! conn->id_verified)
  876.             {
  877.             RefuseAccess(conn,sendbuffer);
  878.             return false;
  879.             }
  880.              
  881.                      bzero(filename,bufsize);
  882.                      sscanf(recvbuffer,"SYNCH %ld STAT %[^\n]",&time_no_see,filename);
  883.  
  884.              trem = (time_t) time_no_see;
  885.  
  886.                      if (time_no_see == 0 || filename[0] == '\0')
  887.             {
  888.             break;
  889.             }
  890.              
  891.              if ((tloc = time((time_t *)NULL)) == -1)
  892.                         {
  893.                         sprintf(conn->output,"Couldn't read system clock\n");
  894.             CfLog(cfinform,conn->output,"time");
  895.             SendTransaction(conn,"BAD: clocks out of synch");
  896.             return true;
  897.                         }
  898.  
  899.              drift = (int)(tloc-trem);
  900.  
  901.                      if (DENYBADCLOCKS && (drift*drift > CLOCK_DRIFT*CLOCK_DRIFT))
  902.             {
  903.             sprintf(conn->output,"BAD: Clocks are too far unsynchronized %ld/%ld\n",(long)tloc,(long)trem);
  904.             CfLog(cfinform,conn->output,"");
  905.             SendTransaction(conn,conn->output);
  906.             return true;
  907.             }
  908.              else
  909.             {
  910.             sprintf(conn->output,"Clocks were off by %ld\n",(long)tloc-(long)trem);
  911.             CfLog(cfverbose,conn->output,"");
  912.             StatFile(conn,sendbuffer,filename);
  913.             }
  914.  
  915.              return true;
  916.  
  917.    case cfd_smd5:    bzero(buffer,bufsize);
  918.                      sscanf(recvbuffer,"SMD5 %d",&len);
  919.                      bcopy(recvbuffer+23,out,bufsize-24);
  920.                      cfdecrypt(out,recvbuffer,CFDES1,CFDES2,CFDES3,len);
  921.  
  922.              if (strncmp(recvbuffer,"MD5",3) !=0)
  923.             {
  924.             RefuseAccess(conn,sendbuffer);
  925.             return false;
  926.             }
  927.              /* roll through, no break */
  928.        
  929.    case cfd_md5:
  930.              if (! conn->id_verified)
  931.             {
  932.             RefuseAccess(conn,sendbuffer);
  933.             return false;
  934.             }
  935.              
  936.                      bzero(filename,bufsize);
  937.              bzero(args,bufsize);
  938.              
  939.                      CompareLocalChecksum(conn,sendbuffer,recvbuffer);
  940.              return true;             
  941.    }
  942.  
  943. sprintf (sendbuffer,"BAD: Malformed protocol request\n");
  944. SendTransaction(conn,sendbuffer);
  945. CfLog(cfinform,"Closing connection\n",""); 
  946. return false;
  947. }
  948.  
  949. /**************************************************************/
  950.  
  951. void ExitCleanly()
  952.  
  953. { int i;
  954.  
  955. sprintf(OUTPUT,"Exit -- (waiting for threads), pid = %d\n",getpid());
  956. CfLog(cfinform,OUTPUT,"");
  957. closelog();
  958.  
  959. #ifdef HAVE_PTHREAD_H
  960. /* Do we care about this? 
  961. for (i = 0; i < MAXTHREAD ; i++)
  962.    {
  963.    if (THREADS[i] != NULL)
  964.       {
  965.       pthread_join(THREADS[i],(void **)NULL);
  966.       }
  967.    }
  968.    */
  969. #endif 
  970.  
  971. exit(0);
  972. }
  973.  
  974. /**************************************************************/
  975.  
  976. void AutoExec()
  977.  
  978. { char logbuffer[bufsize], line[bufsize], *sp;
  979.   FILE *pp; 
  980.   int print;
  981.   
  982. alarm(0);
  983. VBUFF[0] = '\0';
  984.  
  985. ExpandVarstring("$(AutoExecCommand)",VBUFF,"");
  986.  
  987. if (strlen(VBUFF) == 0)
  988.    {
  989.    CfLog(cferror,"No $(AutoExecCommand) variable defined","");
  990.    signal(SIGALRM,(void *)AutoExec);
  991.    return;
  992.    }
  993.  
  994. /* Use same lock as for cfrun */
  995.  
  996.  if (!GetLock("cfd","exec",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  997.    {
  998.    sprintf(OUTPUT,"cfd: Couldn't get a lock -- too soon: IfElapsed %d, ExpireAfter %d\n",VIFELAPSED,VEXPIREAFTER);
  999.    CfLog(cferror,OUTPUT,"");
  1000.    
  1001.    return;
  1002.    }
  1003.  
  1004. if (fork() == 0)
  1005.    {
  1006.    signal(SIGPIPE,SIG_IGN);
  1007.    
  1008.    ExpandVarstring("$(AutoExecCommand) --no-splay --inform",VBUFF,"");
  1009.  
  1010.    sprintf(OUTPUT,"Interval expired, executing command %s\n",VBUFF);
  1011.    CfLog(cfinform,OUTPUT,""); 
  1012.  
  1013.    bzero(logbuffer,bufsize);
  1014.  
  1015.    if ((pp = cfpopen(VBUFF,"r")) == NULL)
  1016.       {
  1017.       sprintf(OUTPUT,"Couldn't open pipe to command %s\n",VBUFF);
  1018.       CfLog(cferror,OUTPUT,"cfpopen");
  1019.  
  1020.       return;
  1021.       }
  1022.    
  1023.    while (!feof(pp))
  1024.       {
  1025.       if (ferror(pp))  /* abortable */
  1026.      {
  1027.      fflush(pp);
  1028.      break;
  1029.      }
  1030.       
  1031.       ReadLine(line,1,pp);
  1032.       
  1033.       if (ferror(pp))  /* abortable */
  1034.      {
  1035.      fflush(pp);
  1036.      break;
  1037.      }     
  1038.       
  1039.       print = false;
  1040.       
  1041.       for (sp = line; *sp != '\0'; sp++)
  1042.      {
  1043.      if (! isspace(*sp))
  1044.         {
  1045.         print = true;
  1046.         break;
  1047.         }
  1048.      }
  1049.       
  1050.       if (print)
  1051.      {
  1052.      sprintf(logbuffer,"%s\n",line);
  1053.      CfLog(cfinform,logbuffer,"");
  1054.      }
  1055.       }
  1056.    
  1057.    cfpclose(pp);
  1058.    closelog();
  1059.    return;
  1060.    }
  1061.  
  1062. signal(SIGALRM,(void *)AutoExec);
  1063. alarm(CFD_INTERVAL); 
  1064. }
  1065.  
  1066. /**************************************************************/
  1067. /* Level 4                                                    */
  1068. /**************************************************************/
  1069.  
  1070. MatchClasses(conn)
  1071.  
  1072. struct cfd_connection *conn;
  1073.  
  1074. { char *sp, recvbuffer[bufsize];
  1075.   struct Item *classlist, *ip;
  1076.   int count = 0, n_read;
  1077.  
  1078. Debug("Match classes\n");
  1079.  
  1080. while (true)
  1081.    {
  1082.    count++;
  1083.  
  1084.    if (RecvSocketStream(conn->sd_reply,recvbuffer,bufsize,0) == -1)
  1085.       {
  1086.       if (errno == EINTR) 
  1087.          {
  1088.          continue;
  1089.          }
  1090.       }
  1091.  
  1092.    Debug("Got class buffer %s\n",recvbuffer);
  1093.  
  1094.    if (strncmp(recvbuffer,CFD_TERMINATOR,strlen(CFD_TERMINATOR)) == 0)
  1095.       {
  1096.       if (count == 1)
  1097.      {
  1098.      Debug("No classes were sent, assuming no restrictions...\n");
  1099.      return true;
  1100.      }
  1101.       
  1102.       break;
  1103.       }
  1104.    
  1105.    classlist = SplitStringAsItemList(recvbuffer,' ');
  1106.  
  1107.    for (ip = classlist; ip != NULL; ip=ip->next)
  1108.       {
  1109.       if (IsDefinedClass(ip->name))
  1110.      {
  1111.      Debug("Class %s matched, accepting...\n",ip->name);
  1112.      DeleteItemList(classlist);
  1113.      return true;
  1114.      }
  1115.       
  1116.       if (strcmp(ip->name,CFD_TERMINATOR) == 0)
  1117.      {
  1118.      Debug("No classes matched, rejecting....\n");
  1119.      ReplyNothing(conn);
  1120.      DeleteItemList(classlist);
  1121.      return false;
  1122.      }
  1123.       }
  1124.    }
  1125.  
  1126. ReplyNothing(conn);
  1127. Debug("No classes matched, rejecting....\n");
  1128. DeleteItemList(classlist);
  1129. return false;
  1130. }
  1131.  
  1132. /**************************************************************/
  1133.  
  1134. DoExec(conn,sendbuffer,args)
  1135.  
  1136. struct cfd_connection *conn;
  1137. char *sendbuffer;
  1138. char *args;
  1139.  
  1140. { char buffer[bufsize], line[bufsize], *sp;
  1141.   FILE *pp;
  1142.   int print,i;
  1143.  
  1144. bzero(buffer,bufsize);
  1145.  
  1146. if ((CFSTARTTIME = time((time_t *)NULL)) == -1)
  1147.    {
  1148.    CfLog(cferror,"Couldn't read system clock\n","time");
  1149.    }
  1150.  
  1151. if (GetMacroValue("cfrunCommand") == NULL)
  1152.    {
  1153.    Verbose("cfd: exec request: no cfrunCommand defined\n");
  1154.    sprintf(sendbuffer,"Exec request: no cfrunCommand defined\n");
  1155.    SendTransaction(conn,sendbuffer);
  1156.    return;
  1157.    }
  1158.  
  1159. for (sp = args; *sp != '\0'; sp++) /* Blank out -K -f */
  1160.    {
  1161.    if ((strncmp(sp,"-K",2) == 0) || (strncmp(sp,"-f",2) == 0))
  1162.       {
  1163.       *sp = ' ';
  1164.       *(sp+1) = ' ';
  1165.       }
  1166.    else if (strncmp(sp,"--no-lock",9) == 0)
  1167.       {
  1168.       for (i = 0; i < 9; i++)
  1169.      {
  1170.      *(sp+i) = ' ';
  1171.      }
  1172.       }
  1173.    else if (strncmp(sp,"--file",7) == 0)
  1174.       {
  1175.       for (i = 0; i < 7; i++)
  1176.      {
  1177.      *(sp+i) = ' ';
  1178.      }
  1179.       }
  1180.    }
  1181.  
  1182. if (!GetLock("cfd","exec",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME))
  1183.    {
  1184.    sprintf(sendbuffer,"cfd: Couldn't get a lock -- too soon: IfElapsed %d, ExpireAfter %d\n",VIFELAPSED,VEXPIREAFTER);
  1185.    SendTransaction(conn,sendbuffer);
  1186.    return;
  1187.    }
  1188.  
  1189. ExpandVarstring("$(cfrunCommand) --no-splay --inform",buffer,"");
  1190.  
  1191. if (strlen(buffer)+strlen(args)+6 > bufsize)
  1192.    {
  1193.    sprintf(sendbuffer,"Command line too long with args: %s\n",buffer);
  1194.    SendTransaction(conn,sendbuffer);
  1195.    ReleaseCurrentLock();
  1196.    return;
  1197.    }
  1198. else
  1199.    {
  1200.    if ((args != NULL) & (strlen(args) > 0))
  1201.       {
  1202.       strcat(buffer," ");
  1203.       strcat(buffer,args);
  1204.  
  1205.       sprintf(sendbuffer,"cfd: Executing %s\n",buffer);
  1206.       SendTransaction(conn,sendbuffer);
  1207.       }
  1208.    }
  1209.  
  1210. sprintf(conn->output,"Executing command %s\n",buffer);
  1211. CfLog(cfinform,conn->output,""); 
  1212.  
  1213. bzero(sendbuffer,bufsize);
  1214.  
  1215. if ((pp = cfpopen(buffer,"r")) == NULL)
  1216.    {
  1217.    sprintf(conn->output,"Couldn't open pipe to command %s\n",buffer);
  1218.    CfLog(cferror,conn->output,"pipe");
  1219.  
  1220.    sprintf(sendbuffer,"Unable to run %s\n",buffer);
  1221.    SendTransaction(conn,sendbuffer);
  1222.    ReleaseCurrentLock();
  1223.    return;
  1224.    }
  1225.  
  1226. while (!feof(pp))
  1227.    {
  1228.    if (ferror(pp))  /* abortable */
  1229.       {
  1230.       fflush(pp);
  1231.       break;
  1232.       }
  1233.  
  1234.    ReadLine(line,bufsize,pp);
  1235.    
  1236.    if (ferror(pp))  /* abortable */
  1237.       {
  1238.       fflush(pp);
  1239.       break;
  1240.       }     
  1241.  
  1242.    print = false;
  1243.      
  1244.    for (sp = line; *sp != '\0'; sp++)
  1245.       {
  1246.       if (! isspace(*sp))
  1247.      {
  1248.      print = true;
  1249.      break;
  1250.      }
  1251.       }
  1252.      
  1253.    if (print)
  1254.       {
  1255.       sprintf(sendbuffer,"%s\n",line);
  1256.       SendTransaction(conn,sendbuffer);
  1257.       }
  1258.   }
  1259.       
  1260. cfpclose(pp);
  1261. ReleaseCurrentLock();
  1262. }
  1263.  
  1264.  
  1265. /**************************************************************/
  1266.  
  1267. GetCommand (str)
  1268.  
  1269. char *str;
  1270.  
  1271. { int i;
  1272.   char op[bufsize];
  1273.  
  1274. sscanf(str,"%4095s",op);
  1275.  
  1276. for (i = 0; COMMANDS[i] != NULL; i++)
  1277.    {
  1278.    if (strcmp(op,COMMANDS[i])==0)
  1279.       {
  1280.       return i;
  1281.       }
  1282.    }
  1283.  
  1284. return -1;
  1285. }
  1286.  
  1287. /*********************************************************************/
  1288.  
  1289. VerifyConnection(conn,buf)
  1290.  
  1291.  /* Try reverse tcpwrap (if we have it), reverse DNS lookup
  1292.     and RFC931 username lookup to check the authenticity. */
  1293.  
  1294. struct cfd_connection *conn;
  1295. char buf[bufsize];
  1296.  
  1297. { struct sockaddr_in raddr,laddr;
  1298.   char ipstring[maxvarsize], fqname[256], username[256];
  1299.   char name1[256], name2[256], name3[256], rusername[256];
  1300.   struct hostent *hp;
  1301.   int len, i, j, found;
  1302.    
  1303. Debug("Connecting host identifies itself as %s\n",buf);
  1304.  
  1305. bzero(ipstring,maxvarsize);
  1306. bzero(fqname,256);
  1307. bzero(username,256); 
  1308.  
  1309. sscanf(buf,"%255s %255s %255s %8s",ipstring,fqname,username,conn->signature);
  1310. len = sizeof(struct sockaddr_in);
  1311.  
  1312. if (getpeername(conn->sd_reply,(struct sockaddr *)&raddr,&len) == -1)
  1313.    {
  1314.    CfLog(cferror,"Couldn't get socket address\n","getpeername");
  1315.    return false;
  1316.    }
  1317.  
  1318. strcpy(name1,ToLowerStr(fqname));
  1319. strcpy(name2,ToLowerStr(inet_ntoa(raddr.sin_addr))); 
  1320. strcpy(name3,ToLowerStr(ipstring));
  1321.  
  1322. if (strcmp(name2,name3) != 0)
  1323.    {
  1324.    Verbose("IP address mismatch between client's assertion and socket - untrustworthy connection\n");
  1325.    return false;
  1326.    }
  1327. else
  1328.    {
  1329.    Verbose("Socket caller address appears honest\n");
  1330.    strncpy(conn->ipaddr,name3,sizeof(conn->ipaddr)-1);
  1331.    }
  1332.  
  1333. sprintf(conn->output,"Socket originates from %s=%s with signature %8s\n",name2,name1,conn->signature);
  1334. CfLog(cfverbose,conn->output,""); 
  1335.  
  1336. #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
  1337.  
  1338. if (!hosts_ctl("cfd",name1,name2,username))
  1339.    {
  1340.    Verbose("TCPwrap(%s,%s,%s) rejects this packet\n",name1,name2,username);
  1341.    return false;
  1342.    }
  1343.  
  1344. #endif
  1345.  
  1346. /* Do our own checking ... */
  1347.  
  1348. Debug("Attempting to look up hostname %s\n",name1);
  1349.  
  1350. #ifdef HAVE_PTHREAD_H 
  1351. if (pthread_mutex_lock(&MUTEX_HOSTNAME) != 0)
  1352.    {
  1353.    CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");
  1354.    return false;
  1355.    }
  1356. #endif 
  1357.  
  1358. if ((hp = gethostbyname(name1)) == NULL)
  1359.    {
  1360.    Verbose("cfd: Couldn't look up name %s\n",fqname);
  1361.    Verbose("     Make sure that fully qualified names can be looked up at your site!\n");
  1362.    Verbose("     i.e. prep.ai.mit.edu, not just prep. If you use NIS or /etc/hosts\n");
  1363.    Verbose("     make sure that the full form is registered too as an alias!\n");
  1364.  
  1365. #ifdef HAVE_PTHREAD_H    
  1366.    if (pthread_mutex_unlock(&MUTEX_HOSTNAME) != 0)
  1367.       {
  1368.       CfLog(cferror,"pthread_mutex_unlock failed","unlock");
  1369.       }
  1370. #endif 
  1371.    
  1372.       
  1373.    return false;
  1374.    }
  1375.  
  1376. #ifdef HAVE_PTHREAD_H  
  1377. if (pthread_mutex_unlock(&MUTEX_HOSTNAME) != 0)
  1378.    {
  1379.    CfLog(cferror,"pthread_mutex_unlock failed","unlock");
  1380.    exit(1);
  1381.    }
  1382. #endif 
  1383.  
  1384.  
  1385.     /* Now let's verify that the ip which gave us this hostname
  1386.      * is really an ip for this hostname; or is someone trying to
  1387.      * break in? (THIS IS THE CRUCIAL STEP)
  1388.      * Patch from Gunnar Gunnarsson, Ericsson */
  1389.  
  1390.  for (i = 0; hp->h_addr_list[i]; i++)
  1391.     {
  1392.     if (memcmp(hp->h_addr_list[i],(char *)&(raddr.sin_addr),sizeof(raddr.sin_addr)) == 0)
  1393.        {
  1394.        break;                     /* name is good, keep it */
  1395.        }
  1396.     }
  1397.  
  1398.  /* If we did not find it, your DNS is messed up or someone is trying
  1399.   * to pull a fast one on you. :(
  1400.   */
  1401.  
  1402.  /*   Check even the aliases list. Work around for Solaris if dns goes over NIS */
  1403.  
  1404.  if (!hp->h_addr_list[i])
  1405.     {
  1406.     for (j=0;hp->h_aliases[j]!=0;j++)
  1407.        {
  1408.        if (strcmp(hp->h_aliases[j],name2) == 0)
  1409.       {
  1410.       break;                          /* name is good, keep it */
  1411.       }
  1412.        }
  1413.     }
  1414.  
  1415.  
  1416.  if (!hp->h_addr_list[i] && !hp->h_aliases[j])
  1417.     {
  1418.     sprintf(conn->output,"Reverse hostname lookup failed, host claiming to be %s was %s\n",buf,inet_ntoa(raddr.sin_addr));
  1419.     CfLog(cfinform,conn->output,"");
  1420.     return false;
  1421.     }
  1422.  
  1423. Debug("Host ID is %s\n",name1);
  1424. strncpy(conn->hostname,name1,maxvarsize);
  1425.  
  1426. if (getsockname(conn->sd_reply,(struct sockaddr *)&laddr,&len) == -1)
  1427.    {
  1428.    CfLog(cferror,"Couldn't get socket address\n","getsockname");
  1429.    return false;
  1430.    }
  1431.  
  1432. if (CHECK_RFC931)
  1433.    {
  1434.    if (DoRFC931(&(laddr.sin_addr),&(raddr.sin_addr),ntohs(laddr.sin_port),ntohs(raddr.sin_port),rusername))
  1435.       {
  1436.       Debug("Remote host got %s as username, local=%s\n",rusername,username);
  1437.       if (strcmp(ToLowerStr(username),ToLowerStr(rusername)) == 0)
  1438.      {
  1439.      Debug("User ID confirmed as %s\n",username); 
  1440.      strncpy(conn->username,username,maxvarsize);
  1441.      return true;   
  1442.      }
  1443.       else
  1444.      {
  1445.      CfLog(cferror,"Username RFC931 authentication failed","");
  1446.      sprintf(conn->output,"Source spoofed user %s but was actually %s\n",username,rusername);
  1447.      CfLog(cferror,conn->output,"");
  1448.      return false;
  1449.      }
  1450.       }
  1451.    else    
  1452.       {
  1453.       CfLog(cferror,"RFC931 lookup failed on source host\n","");
  1454.       return false;
  1455.       }
  1456.    }
  1457.  
  1458. Debug("User ID seems to be %s\n",username); 
  1459. strncpy(conn->username,username,maxvarsize);
  1460. return true;   
  1461. }
  1462.  
  1463. /**************************************************************/
  1464.  
  1465. RefuseAccess(conn,sendbuffer)
  1466.  
  1467. struct cfd_connection *conn;
  1468. char *sendbuffer;
  1469.  
  1470. {
  1471. sprintf(sendbuffer,"%s",CFFAILEDSTR);
  1472. CfLog(cfinform,"Host authentication failed or access denied\n","");
  1473.  
  1474. SendTransaction(conn,sendbuffer);
  1475. }
  1476.  
  1477. /**************************************************************/
  1478.  
  1479. AccessControl(filename,conn,secure)
  1480.  
  1481. char *filename;
  1482. struct cfd_connection *conn;
  1483. int secure;
  1484.  
  1485. { struct Auth *ap;
  1486.   int access = false;
  1487.   char realname[bufsize];
  1488.   struct stat statbuf;
  1489.  
  1490. Debug("AccessControl(%s)\n",filename);
  1491. bzero(realname,bufsize);
  1492.  
  1493. #ifdef HAVE_REALPATH
  1494. if (realpath(filename,realname) == NULL)
  1495.    {
  1496.    sprintf(conn->output,"Couldn't resolve filename %s from host %s\n",filename,conn->hostname);
  1497.    CfLog(cferror,conn->output,"");
  1498.    return false;
  1499.    }
  1500. #else
  1501. CompressPath(realname,filename); /* in links.c */
  1502. #endif
  1503.   
  1504. Debug("AccessControl(%s,%s) secure=%d\n",realname,conn->hostname,secure);
  1505.   
  1506. if (VADMIT == NULL)
  1507.    {
  1508.    Verbose("cfd: access list is empty, no files are visible\n");
  1509.    return false;
  1510.    }
  1511.  
  1512. conn->maproot = false;
  1513.  
  1514. for (ap = VADMIT; ap != NULL; ap=ap->next)
  1515.    {
  1516.    if (strncmp(ap->path,realname,strlen(ap->path)) == 0)
  1517.       {
  1518.       if (stat(ap->path,&statbuf) == -1)
  1519.      {
  1520.      Verbose("Warning cannot stat file object %s in admit/grant\n",ap->path);
  1521.      continue;
  1522.      }
  1523.       
  1524.       if (!secure && (ap->secure == true))
  1525.      {
  1526.      Debug("File requires secure connection...will not serve\n");
  1527.      access = false;
  1528.      }
  1529.       else
  1530.      {
  1531.      if (access = IsWildItemIn(ap->accesslist,conn->hostname))
  1532.         {
  1533.         }
  1534.      else
  1535.         {
  1536.         access = IsWildItemIn(ap->accesslist,conn->ipaddr);
  1537.         }
  1538.  
  1539.      if (IsWildItemIn(ap->maproot,conn->hostname))
  1540.         {
  1541.         conn->maproot = true;
  1542.         }
  1543.      else if (IsWildItemIn(ap->maproot,conn->ipaddr))
  1544.         {
  1545.         conn->maproot = true;
  1546.         }
  1547.      }
  1548.       break;
  1549.       }
  1550.    }
  1551.  
  1552. for (ap = VDENY; ap != NULL; ap=ap->next)
  1553.    {
  1554.    if (strncmp(ap->path,realname,strlen(ap->path)) == 0)
  1555.       {
  1556.       if (IsWildItemIn(ap->accesslist,conn->hostname))
  1557.          {
  1558.          access = false;
  1559.          break;
  1560.          }
  1561.       }
  1562.    }
  1563.  
  1564. if (access)
  1565.    {
  1566.    sprintf(conn->output,"Host %s granted access to %s\n",conn->hostname,realname);
  1567.    CfLog(cfverbose,conn->output,"");
  1568.    }
  1569. else
  1570.    {
  1571.    sprintf(conn->output,"Host %s denied access to %s\n",conn->hostname,realname);
  1572.    CfLog(cfinform,conn->output,"");
  1573.    }
  1574.  
  1575. return access;
  1576. }
  1577.  
  1578. /**************************************************************/
  1579.  
  1580. StatFile(conn,sendbuffer,filename)
  1581.  
  1582. struct cfd_connection *conn;
  1583. char *sendbuffer, *filename;
  1584.  
  1585. /* Because we do not know the size or structure of remote datatypes,*/
  1586. /* the simplest way to transfer the data is to convert them into */
  1587. /* plain text and interpret them on the other side. */
  1588.  
  1589. { struct cfstat cfst;
  1590.   struct stat statbuf;
  1591.   char linkbuf[bufsize];
  1592.  
  1593.   Debug("StatFile(%s)\n",filename);
  1594.  
  1595. bzero(&cfst,sizeof(struct cfstat));
  1596.   
  1597. if (strlen(filename) > maxlinksize)
  1598.    {
  1599.    sprintf(sendbuffer,"BAD: Filename suspiciously long\n");
  1600.    CfLog(cferror,sendbuffer,"");
  1601.    SendTransaction(conn,sendbuffer);
  1602.    return -1;
  1603.    }
  1604.  
  1605. if (lstat(filename,&statbuf) == -1)
  1606.    {
  1607.    sprintf(sendbuffer,"BAD: unable to stat file %s",filename);
  1608.    CfLog(cfverbose,sendbuffer,"lstat");
  1609.    SendTransaction(conn,sendbuffer);
  1610.    return -1;
  1611.    }
  1612.  
  1613. cfst.cf_readlink = NULL;
  1614. cfst.cf_lmode = 0;
  1615. cfst.cf_nlink = cfnosize;
  1616.  
  1617. bzero(linkbuf,bufsize);
  1618.  
  1619. if (S_ISLNK(statbuf.st_mode))
  1620.    {
  1621.    cfst.cf_type = cf_link;                   /* pointless - overwritten */
  1622.    cfst.cf_lmode = statbuf.st_mode & 07777;
  1623.    cfst.cf_nlink = statbuf.st_nlink;
  1624.        
  1625.    if (readlink(filename,linkbuf,bufsize) == -1)
  1626.       {
  1627.       sprintf(sendbuffer,"BAD: unable to read link\n");
  1628.       CfLog(cferror,sendbuffer,"readlink");
  1629.       SendTransaction(conn,sendbuffer);
  1630.       return -1;
  1631.       }
  1632.  
  1633.    Debug("readlink: %s\n",linkbuf);
  1634.  
  1635.    cfst.cf_readlink = linkbuf;
  1636.    }
  1637.  
  1638. if (stat(filename,&statbuf) == -1)
  1639.    {
  1640.    sprintf(sendbuffer,"BAD: unable to stat file %s\n",filename);
  1641.    CfLog(cfverbose,conn->output,"stat");
  1642.    SendTransaction(conn,sendbuffer);
  1643.    return -1;
  1644.    }
  1645.  
  1646. if (S_ISDIR(statbuf.st_mode))
  1647.    {
  1648.    cfst.cf_type = cf_dir;
  1649.    }
  1650.  
  1651. if (S_ISREG(statbuf.st_mode))
  1652.    {
  1653.    cfst.cf_type = cf_reg;
  1654.    }
  1655.  
  1656. if (S_ISSOCK(statbuf.st_mode))
  1657.    {
  1658.    cfst.cf_type = cf_sock;
  1659.    }
  1660.  
  1661. if (S_ISCHR(statbuf.st_mode))
  1662.    {
  1663.    cfst.cf_type = cf_char;
  1664.    }
  1665.  
  1666. if (S_ISBLK(statbuf.st_mode))
  1667.    {
  1668.    cfst.cf_type = cf_block;
  1669.    }
  1670.  
  1671. if (S_ISFIFO(statbuf.st_mode))
  1672.    {
  1673.    cfst.cf_type = cf_fifo;
  1674.    }
  1675.  
  1676. cfst.cf_mode     = statbuf.st_mode  & 07777;      /* Make sure everything is 32 bit */
  1677. cfst.cf_uid      = statbuf.st_uid   & 0xFFFFFFFF;
  1678. cfst.cf_gid      = statbuf.st_gid   & 0xFFFFFFFF;
  1679. cfst.cf_size     = statbuf.st_size  & 0xFFFFFFFF;
  1680. cfst.cf_atime    = statbuf.st_atime & 0xFFFFFFFF;
  1681. cfst.cf_mtime    = statbuf.st_mtime & 0xFFFFFFFF;
  1682. cfst.cf_ctime    = statbuf.st_ctime & 0xFFFFFFFF;
  1683. cfst.cf_ino      = statbuf.st_ino;
  1684. cfst.cf_readlink = linkbuf;
  1685.  
  1686. if (cfst.cf_nlink == cfnosize)
  1687.    {
  1688.    cfst.cf_nlink = statbuf.st_nlink;
  1689.    }
  1690.  
  1691. #ifndef IRIX
  1692. if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE)
  1693. #else
  1694. # ifdef HAVE_ST_BLOCKS
  1695. if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE)
  1696. # else
  1697. if (statbuf.st_size > ST_NBLOCKS(statbuf) * DEV_BSIZE)
  1698. # endif
  1699. #endif
  1700.    {
  1701.    cfst.cf_makeholes = 1;   /* must have a hole to get checksum right */
  1702.    }
  1703. else
  1704.    {
  1705.    cfst.cf_makeholes = 0;
  1706.    }
  1707.  
  1708.  
  1709. bzero(sendbuffer,bufsize);
  1710.  
  1711.  /* send as plain text */
  1712.  
  1713. Debug("OK: type=%d\n mode=%o\n lmode=%o\n uid=%d\n gid=%d\n size=%ld\n atime=%d\n mtime=%d\n",
  1714.     cfst.cf_type,cfst.cf_mode,cfst.cf_lmode,cfst.cf_uid,cfst.cf_gid,(long)cfst.cf_size,
  1715.     cfst.cf_atime,cfst.cf_mtime);
  1716.  
  1717.  
  1718. sprintf(sendbuffer,"OK: %d %d %d %d %d %ld %d %d %d %d %d %d",
  1719.     cfst.cf_type,cfst.cf_mode,cfst.cf_lmode,cfst.cf_uid,cfst.cf_gid,(long)cfst.cf_size,
  1720.     cfst.cf_atime,cfst.cf_mtime,cfst.cf_ctime,cfst.cf_makeholes,cfst.cf_ino,cfst.cf_nlink);
  1721.  
  1722. SendTransaction(conn,sendbuffer);
  1723. bzero(sendbuffer,bufsize);
  1724.  
  1725. if (cfst.cf_readlink != NULL)
  1726.    {
  1727.    strcpy(sendbuffer,"OK:");
  1728.    strcat(sendbuffer,cfst.cf_readlink);
  1729.    }
  1730. else
  1731.    {
  1732.    sprintf(sendbuffer,"OK:");
  1733.    }
  1734.  
  1735. SendTransaction(conn,sendbuffer);
  1736. return 0;
  1737. }
  1738.  
  1739.  
  1740. /***************************************************************/
  1741.  
  1742. CfGetFile(args)
  1743.  
  1744. struct cfd_get_arg *args;
  1745.  
  1746. { int sd,fd, n_read,total=0,size_at_start,i=0;
  1747.   char sendbuffer[bufsize],out[bufsize],*filename;
  1748.   struct stat statbuf;
  1749.   struct passwd *pw;
  1750.   uid_t uid;
  1751.  
  1752. #ifdef HAVE_UTIME_H
  1753.   struct utimbuf timebuf;
  1754. #endif
  1755.  
  1756. sd         = (args->connect)->sd_reply;
  1757. filename   = args->replyfile;
  1758.  
  1759. if ((pw=getpwnam((args->connect)->username)) == NULL)
  1760.    {
  1761.    uid = -2;
  1762.    }
  1763. else
  1764.    {
  1765.    uid = pw->pw_uid;
  1766.    }
  1767.  
  1768. stat(filename,&statbuf);
  1769. Debug("CfGetFile(%s on sd=%d), size=%d\n",filename,sd,statbuf.st_size);
  1770.  
  1771. size_at_start = statbuf.st_size; 
  1772.  
  1773. /* Now check to see if we have remote permission */
  1774.  
  1775. if (uid != 0 && !args->connect->maproot) /* should remote root be local root */
  1776.    {
  1777.    if (statbuf.st_uid == uid)
  1778.       {
  1779.       Debug("Caller %s is the owner of the file\n",(args->connect)->username);
  1780.       }
  1781.    else
  1782.       {
  1783.       /* We are not the owner of the file and we don't care about groups */
  1784.       if (statbuf.st_mode & S_IROTH)
  1785.      {
  1786.      Debug("Caller %s not owner of the file but permission granted\n",(args->connect)->username);
  1787.      }
  1788.       else
  1789.      {
  1790.      Debug("Caller %s is not the owner of the file\n",(args->connect)->username);
  1791.      RefuseAccess(args->connect,sendbuffer);
  1792.      return;
  1793.      }
  1794.       }
  1795.    }
  1796.  
  1797. if (args->buf_size < 512)
  1798.    {
  1799.    sprintf(args->connect->output,"blocksize for %s was only %d\n",filename,args->buf_size);
  1800.    CfLog(cferror,args->connect->output,"");
  1801.    }
  1802.  
  1803.  if ((fd = open(filename,O_RDONLY)) == -1)
  1804.    {
  1805.    sprintf(sendbuffer,"%s",CFFAILEDSTR);
  1806.    CfLog(cferror,sendbuffer,"open");
  1807.    SendTransaction(args->connect,sendbuffer);
  1808.    sprintf(sendbuffer,"Open error of file [%s]\n",filename);
  1809.    CfLog(cferror,sendbuffer,"open");
  1810.    }
  1811. else
  1812.    {
  1813.    while(true)
  1814.       {
  1815.       bzero(sendbuffer,bufsize);
  1816.  
  1817.       if ((n_read = read(fd,sendbuffer,args->buf_size)) == -1)
  1818.      {
  1819.      close(fd);
  1820.      CfLog(cferror,"read failed in GetFile","read");
  1821.      break;
  1822.      }
  1823.  
  1824.       if (n_read == 0)
  1825.      {
  1826.      close(fd);
  1827.      break;
  1828.      }
  1829.       else
  1830.      { int save = statbuf.st_size;
  1831.  
  1832.      /* This can happen with log files /databases etc */
  1833.      
  1834.      stat(filename,&statbuf);
  1835.      
  1836.      if (statbuf.st_size != save)
  1837.         {
  1838.         sprintf(sendbuffer,"BAD:File %s changed while copying",filename);
  1839.         if (send(sd,sendbuffer,args->buf_size,0) == -1)
  1840.            {
  1841.            CfLog(cferror,"Send failed in GetFile","send");
  1842.            }
  1843.         
  1844.         Debug("Aborting transfer after %d: file is changing rapidly at source.\n",total);
  1845.         close(fd);     
  1846.         break;
  1847.         }
  1848.      }
  1849.       
  1850.       total += n_read;
  1851.  
  1852.       if (args->secure)
  1853.      {
  1854.      bzero(out,bufsize);
  1855.      cfencrypt(sendbuffer,out,CFDES1,args->key,CFDES3,args->buf_size); /* use session key */
  1856.  
  1857.      /* Need to pad out to buf_size rather than stop at n_read
  1858.         because encryption requires an 8-byte divisible block  */
  1859.      
  1860.      if (send(sd,out,args->buf_size,0) == -1)
  1861.         {
  1862.         close(fd);
  1863.         CfLog(cferror,"Send failed in GetFile","send");
  1864.         break;
  1865.         }
  1866.      }
  1867.       else
  1868.      {
  1869.      if (send(sd,sendbuffer,args->buf_size,0) == -1)
  1870.         {
  1871.         close(fd);
  1872.         CfLog(cferror,"Send failed in GetFile","send");
  1873.         break;
  1874.         }
  1875.      }
  1876.       }
  1877.    }
  1878.  
  1879. Debug("Done with GetFile()\n"); 
  1880. }
  1881.  
  1882. /**************************************************************/
  1883.  
  1884. CompareLocalChecksum(conn,sendbuffer,recvbuffer)
  1885.  
  1886. struct cfd_connection *conn;
  1887. char *sendbuffer, *recvbuffer;
  1888.  
  1889. { unsigned char digest[17], num[5],filename[bufsize];
  1890.   char *sp;
  1891.   int i,len;
  1892.  
  1893. sscanf(recvbuffer,"MD5 %[^\n]",filename);
  1894.  
  1895. sp = recvbuffer+6+strlen(filename); /* Finr md5 */
  1896.  
  1897.  Debug("Got filename %s, sp=%s\n",filename,sp);
  1898.  
  1899. for (i = 0; i < 16; i++)
  1900.    {
  1901.    bzero(num,5);
  1902.    sscanf(sp,"%4s",num);
  1903.    digest[i] = (char) atoi(num);
  1904.    sp += strlen((char *)num) + 1;
  1905.    }
  1906.  
  1907. Debug("CompareLocalChecksums(%s)\n",cfMDPrint(digest));
  1908. bzero(sendbuffer,bufsize);
  1909.  
  1910. if (ChecksumChanged(filename,digest,cfverbose,true))
  1911.    {
  1912.    sprintf(sendbuffer,"%s",CFD_TRUE);
  1913.    Debug("Checksums didn't match\n");
  1914.    SendTransaction(conn,sendbuffer);
  1915.    return;
  1916.    }
  1917. else
  1918.    {
  1919.    sprintf(sendbuffer,"%s",CFD_FALSE);
  1920.    Debug("Checksums matched ok\n");
  1921.    SendTransaction(conn,sendbuffer);
  1922.    }
  1923. }
  1924.  
  1925. /**************************************************************/
  1926.  
  1927. CfOpenDirectory(conn,sendbuffer,dirname)
  1928.  
  1929. struct cfd_connection *conn;
  1930. char *sendbuffer, *dirname;
  1931.  
  1932. { DIR *dirh;
  1933.   struct dirent *dirp;
  1934.   int offset;
  1935.  
  1936. Debug("CfOpenDirectory(%s)\n",dirname);
  1937.   
  1938. if (*dirname != '/')
  1939.    {
  1940.    sprintf(sendbuffer,"BAD: request to access a non-absolute filename\n");
  1941.    SendTransaction(conn,sendbuffer);
  1942.    return -1;
  1943.    }
  1944.  
  1945. if ((dirh = opendir(dirname)) == NULL)
  1946.    {
  1947.    Debug("cfengine, couldn't open dir %s\n",dirname);
  1948.    sprintf(sendbuffer,"BAD: cfengine, couldn't open dir %s\n",dirname);
  1949.    SendTransaction(conn,sendbuffer);
  1950.    return -1;
  1951.    }
  1952.  
  1953. /* Pack names for transmission */
  1954.  
  1955. bzero(sendbuffer,bufsize);
  1956.  
  1957. offset = 0;
  1958.  
  1959. for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
  1960.    {
  1961.    if (strlen(dirp->d_name)+1+offset >= bufsize - buffer_margin)
  1962.       {
  1963.       SendTransaction(conn,sendbuffer);
  1964.       offset = 0;
  1965.       bzero(sendbuffer,bufsize);
  1966.       }
  1967.  
  1968.    strncpy(sendbuffer+offset,dirp->d_name,maxlinksize);
  1969.    offset += strlen(dirp->d_name) + 1;     /* + zero byte separator */
  1970.    }
  1971.  
  1972. strcpy(sendbuffer+offset,CFD_TERMINATOR);
  1973.  
  1974. SendTransaction(conn,sendbuffer);
  1975. closedir(dirh);
  1976. return 0;
  1977. }
  1978.  
  1979. /***************************************************************/
  1980.  
  1981. Terminate(sd)
  1982.  
  1983. int sd;
  1984.  
  1985. { char buffer[bufsize];
  1986.  
  1987. bzero(buffer,bufsize);
  1988.  
  1989. strcpy(buffer,CFD_TERMINATOR);
  1990.  
  1991. if (send(sd,buffer,strlen(buffer)+1,0) == -1)
  1992.    {
  1993.    CfLog(cferror,"","send");
  1994.    Verbose("Unable to reply with terminator...\n");
  1995.    }
  1996. }
  1997.  
  1998. /***************************************************************/
  1999.  
  2000. DeleteAuthList(ap)
  2001.  
  2002. struct Auth *ap;
  2003.  
  2004. {
  2005. if (ap != NULL)
  2006.    {
  2007.    DeleteAuthList(ap->next);
  2008.    ap->next = NULL;
  2009.  
  2010.    DeleteItemList(ap->accesslist);
  2011.  
  2012.    free((char *)ap);
  2013.    }
  2014. }
  2015.  
  2016. /***************************************************************/
  2017. /* Level 5                                                     */
  2018. /***************************************************************/
  2019.  
  2020. DoRFC931(laddr,raddr,local,remote,username)
  2021.  
  2022. /* Not many OSes have this authentication service, alas */
  2023.  
  2024. struct in_addr *laddr, *raddr;
  2025. unsigned short local,remote;
  2026. char username[256];
  2027.  
  2028. { struct sockaddr_in saddr;
  2029.   char sendbuffer[maxvarsize],recvbuffer[bufsize], *sp;
  2030.   int n_read, sd, yes=1;
  2031.  
  2032.  if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  2033.     {
  2034.     return false;
  2035.     }
  2036.  
  2037.  /* Identify ourselves with this address */
  2038.  
  2039.  bind(sd,(struct sockaddr *)laddr,sizeof(laddr));
  2040.  
  2041.  setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof(int));
  2042.  
  2043.  saddr.sin_family = AF_INET;
  2044.  saddr.sin_port = htons(RFC931_PORT);
  2045.  saddr.sin_addr.s_addr = raddr->s_addr;
  2046.  
  2047.  if (connect(sd,(struct sockaddr *)&saddr,sizeof(saddr)) == -1)
  2048.     {
  2049.     CfLog(cferror,"Couldn't connect to verify RFC931\n","connect");
  2050.     close(sd);
  2051.     return false;
  2052.     }
  2053.  
  2054.   /* The RFC document is misleading...careful with order */
  2055.  
  2056.  sprintf(sendbuffer,"%u , %u\r\n",(unsigned int)remote,(unsigned int)local);
  2057.  
  2058.  if (send(sd,sendbuffer,strlen(sendbuffer),0) == -1)
  2059.     {
  2060.     CfLog(cferror,"Couldn't send to verify RFC931\n","send");
  2061.     close(sd);
  2062.     return false;
  2063.     }
  2064.  
  2065.  if ((n_read = recv(sd, recvbuffer, bufsize,0)) == -1)
  2066.     {
  2067.     CfLog(cferror,"Couldn't recv to verify RFC931\n","recv");
  2068.     close(sd);
  2069.     return false;
  2070.     }
  2071.  
  2072. close(sd);
  2073.  
  2074. Debug("AUTH server returned %s\n",recvbuffer);
  2075.  
  2076. if (strstr(recvbuffer,"ERROR"))
  2077.    {
  2078.    Verbose("RFC931 checking reveals no such user connection at source!\n");
  2079.    return false;
  2080.    }
  2081.  
  2082. /* e.g. AUTH server returned 8530 , 5308 : USERID : UNIX : mark  */
  2083.  
  2084. for (sp = recvbuffer; *sp != ':'; sp++)
  2085.    {
  2086.    }
  2087.  
  2088. sp++;
  2089.  
  2090. while (*sp != ':')
  2091.    {
  2092.    sp++;
  2093.    } 
  2094.  
  2095. sp++;
  2096.  
  2097. sendbuffer[0] = '\0';
  2098. username[0] = '\0';
  2099. Debug("Checking %s\n",sp); 
  2100. sscanf(sp,"%255s %*[:] %255s",sendbuffer,username);
  2101.  
  2102. Debug("Operating system type of remote host was %s and user was %s\n",sendbuffer,username);
  2103. return true; 
  2104. }
  2105.  
  2106.  
  2107. /***************************************************************/
  2108.  
  2109. ReplyNothing(conn)
  2110.  
  2111. struct cfd_connection *conn;
  2112.  
  2113. { char buffer[bufsize];
  2114.  
  2115. sprintf(buffer,"Hello %s, nothing to do here...\n",conn->hostname,VFQNAME);
  2116.  
  2117. if (send(conn->sd_reply,buffer,bufsize,0) == -1)
  2118.    {
  2119.    CfLog(cferror,"","send");
  2120.    }
  2121. }
  2122.  
  2123. /***************************************************************/
  2124. /* Toolkit/Class: conn                                         */
  2125. /***************************************************************/
  2126.  
  2127. struct cfd_connection *NewConn(sd)  /* construct */
  2128.  
  2129. int sd;
  2130.  
  2131. { struct cfd_connection *conn;
  2132.  
  2133. conn = (struct cfd_connection *) malloc(sizeof(struct cfd_connection));
  2134.  
  2135. conn->sd_reply = sd;
  2136. conn->id_verified = false;
  2137. conn->hostname[0] = '\0'; 
  2138. Debug("***New socket %d\n",sd);
  2139.  
  2140. return conn;
  2141. }
  2142.  
  2143. /***************************************************************/
  2144.  
  2145. DeleteConn(conn) /* destruct */
  2146.  
  2147. struct cfd_connection *conn;
  2148.  
  2149. {
  2150. Debug("***Closing socket %d\n",conn->sd_reply);
  2151. close(conn->sd_reply);
  2152. free ((char *)conn);
  2153. }
  2154.  
  2155. /*************************************************************************/
  2156.  
  2157. SendTransaction(conn,buffer)
  2158.  
  2159. struct cfd_connection *conn;
  2160. char *buffer;
  2161.  
  2162. {
  2163. /* Send a fixed size transmission
  2164.    so that it will be read at the other end */
  2165. Debug("SendTransaction()\n");
  2166. if (send(conn->sd_reply,buffer,bufsize,0) == -1)
  2167.    {
  2168.    CfLog(cferror,"Couldn't send","send");
  2169.    return -1;
  2170.    }
  2171. }
  2172.  
  2173.  
  2174. /* EOF */
  2175.  
  2176.  
  2177.  
  2178.